// 重构后的类型定义
interface BaseSchemaField<T> {
  type: T
  required?: boolean
  message?: Record<string, string>
  default?: any
  desc?: string
  pattern?: (val: any) => boolean
}

export type SchemaField<T extends string> = T extends 'number' ? BaseSchemaField<T> & {
  min?: number
  max?: number
  message?: { min?: string, max?: string, type?: string, required?: string }
} : T extends 'string' ? BaseSchemaField<T> & {
  maxLength?: number
  message?: { maxLength?: string, pattern?: string, type?: string, required?: string }
} : T extends 'object' ? BaseSchemaField<T> & {
  properties?: SchemaDefine
  default?: () => Record<string, any>
  message?: { type?: string }
} : T extends 'array' ? BaseSchemaField<T> & {
  message?: { type?: string }
  default?: () => any[]
} : BaseSchemaField<T>

interface SchemaDefine {
  [key: string]: SchemaField<'number' | 'string' | 'object' | 'array' | 'boolean'>
}

export function validate(validatedParams: Record<string, any>, schema: SchemaDefine): { valid: boolean, errors: string[], data?: Record<string, any> } {
  const errors: string[] = []
  const addError = (message: string) => errors.push(message)

  const normalizeRule = (rule: any, paramName: string, value: any) => {
    if (!rule.type) return null

    const normalize: {
      type: string
      default: any
      required: boolean
      validate: (val: any, rule?: any) => boolean
      message: string
    } = {
      type: rule.type,
      default: rule.default,
      required: rule.required !== undefined ? rule.required : true,
      validate: rule.pattern || (() => true),
      message: '',
    }

    const getErrorMessage = (messageType: string, defaultMessage: string) =>
      (rule.message && rule.message[messageType]) ?? defaultMessage

    // 必填校验
    if (normalize.required && (value === undefined || value === null)) {
      normalize.validate = (val: null | undefined) => val !== null && val !== undefined
      normalize.message = getErrorMessage('required', `Parameter "${paramName}" is required.`)
      return normalize
    }

    // 如果值未定义且非必需，则跳过验证
    if (value === undefined && !normalize.required) {
      return null
    }

    if (rule.pattern) {
      normalize.validate = (val: any) => typeof val !== 'undefined' && rule.pattern(val)
      normalize.message = getErrorMessage('pattern', `Parameter "${paramName}" does not match required pattern.`)
      return normalize
    }

    if (normalize.type === 'object') {
      if (rule.properties) {
        const result = validate(value || {}, rule.properties || {})
        errors.push(...result.errors)
        return null
      }
      normalize.validate = (val: any) => val !== null && typeof val === 'object' && !Array.isArray(val)
      normalize.message = getErrorMessage('type', `Parameter "${paramName}" must be object`)
      return normalize
    }

    if (normalize.type === 'array') {
      normalize.validate = (val: any) => Array.isArray(val)
      normalize.message = getErrorMessage('type', `Parameter "${paramName}" must be array`)
      return normalize
    }

    if (normalize.type === 'number') {
      const numValue = Number(value)
      validatedParams[paramName] = numValue

      if (typeof numValue !== 'number' || Number.isNaN(numValue)) {
        normalize.validate = () => false
        normalize.message = getErrorMessage('type', `Parameter "${paramName}" must be number`)
        return normalize
      }

      const hasMin = typeof rule.min === 'number'
      const hasMax = typeof rule.max === 'number'

      if (hasMin && hasMax) {
        normalize.validate = (val: number) => (val >= rule.min && val <= rule.max)
        normalize.message = getErrorMessage('min', `Parameter "${paramName}" must be between ${rule.min} and ${rule.max}.`)
        return normalize
      }
      if (hasMin) {
        normalize.validate = (val: number) => val >= rule.min
        normalize.message = getErrorMessage('min', `Parameter "${paramName}" must be greater than ${rule.min}.`)
        return normalize
      }
      if (hasMax) {
        normalize.validate = (val: number) => val <= rule.max
        normalize.message = getErrorMessage('max', `Parameter "${paramName}" must be less than ${rule.max}.`)
        return normalize
      }
      return normalize
    }

    if (rule.type === 'string') {
      if (typeof value !== 'string') {
        normalize.validate = () => false
        normalize.message = getErrorMessage('type', `Parameter "${paramName}" must be string`)
        return normalize
      }

      if (rule.maxLength) {
        normalize.validate = (val: string) => val.length <= rule.maxLength
        normalize.message = getErrorMessage('maxLength', `Parameter "${paramName}" must be at most ${rule.maxLength} characters long.`)
        return normalize
      }
      return normalize
    }

    if (rule.type === 'boolean') {
      normalize.validate = (val: any) => typeof val === 'boolean'
      return normalize
    }

    return normalize
  }

  for (const paramName in schema) {
    let value = validatedParams[paramName]
    const rule = schema[paramName]

    // 处理默认值
    if ((value === undefined || value === null) && rule.default !== undefined) {
      value = validatedParams[paramName] = typeof rule.default === 'function' ? rule.default() : rule.default
    }

    const res = normalizeRule(rule, paramName, value)

    if (!res) continue

    const validationResult = res.validate(value, rule)
    if (!validationResult) {
      addError(res.message)
      break
    }
  }

  return {
    valid: errors.length === 0,
    errors,
    data: errors.length === 0 ? validatedParams : undefined,
  }
}
